#include"server.h"
#define ERR_LOG(msg) do{                                \
    cerr << __FILE__ << __func__ << __LINE__ << endl;   \
    perror(msg);                                        \
}while(false)

Server::Server(shared_ptr<DatabaseManager> db_manager, shared_ptr<ThreadPool> thread_pool, const string &ip, unsigned short port):db_ptr_(db_manager), t_pool_(thread_pool), ip_(ip), port_(port), running_(false)
{
    sfd_ = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd_ < 0)
    {
        throw runtime_error("socker error");
    }

    sockaddr_in saddr;

    saddr.sin_addr.s_addr = inet_addr(ip_.c_str());
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port_);

    if(bind(sfd_, (sockaddr *)&saddr, sizeof saddr) < 0)
    {
        close(sfd_);
        throw runtime_error("bind error");
    }

    // 转换成队列
    if (listen(sfd_, 8) < 0)
    {
        close(sfd_);
        throw runtime_error("listen error");
    }
}

Server::~Server()
{
    stop();

    if(sfd_)
        close(sfd_);
}

bool Server::start()
{
    running_ = true;

    sockaddr_in caddr;
    socklen_t caddr_len = sizeof caddr;

    while(running_)
    {
        int cfd = accept(sfd_, (sockaddr *)&caddr, &caddr_len);
        if(cfd < 0)
        {
            if(running_) ERR_LOG("accept error");
            continue;
        }
        // 添加任务
        t_pool_->add([this, cfd, caddr]()
                     { handleClient(cfd, caddr); });
    }

    return true;
}

void Server::handleClient(int sfd, sockaddr_in caddr)
{
    char buf[Msg::getLen()] = "";
    Msg msg;
    while (true)
    {
        // 接收客户端消息
        int res = recv(sfd, buf, sizeof buf, 0);
        if(res < 0)
        {
            ERR_LOG("recv error");
            break;
        }
        else if(res == 0)
        {
            // 客户端下线
            break;
        }

        // 程序执行至此表示正常读取
        msg.Reserialization(buf);
        msg.ntoh();

        // 回复给对方的消息
        Msg response;
        strcpy(response.name, msg.name);
        response.type = msg.type;
        response.hton();

        if(msg.type == REGISTER)
        {
            if(db_ptr_->registerUser(string(msg.name), string(msg.text)))
            { // 注册成功
                strcpy(response.text, "Register Success");
            }
            else
            { // 注册失败
                strcpy(response.text, "Register Error");
            }
        }
        else if(msg.type == LOGIN)
        {
            bool is_online = false;
            // 账号密码正确，记录用户是否在线
            if (db_ptr_->loginUser(string(msg.name), string(msg.text), is_online))
            {
                if(is_online)
                    strcpy(response.text, "Exits");
                else
                    strcpy(response.text, "Login Success");
            }
            else
                strcpy(response.text, "UserName Or Password Error");
        }
        else if(msg.type == LOGOUT)
        {
            if(db_ptr_->logoutUser(msg.name))
                strcpy(response.text, "Logout Success");
            else
                strcpy(response.text, "Logout Error");
        }
        else if(msg.type == SELECT)
        {
            string meaning; // 保存单词的含义
            if(db_ptr_->queryWord(string(msg.text), meaning))
            { // 查询成功则返回单词的含义
                snprintf(response.text, sizeof response.text, "%s %s", msg.text, meaning.c_str());
            }
            else
            { // 查询失败
                strcpy(response.text, "Select error");
            }
            // 将本次查询记录插入到系统表
            db_ptr_->recordHistory(msg.name, msg.text, meaning, getCurrentTime());
        }
        else if(msg.type == HISTORY)
        {   // 执行查看历史记录操作
            string history;
            if(db_ptr_->getHistory(msg.name, history))
            {   // 查询历史记录
                //写入历史记录
                for (int i = 0; i < history.size();)
                {
                    // 历史记录的终点
                    int r = i;  // 查找历史记录的终点
                    for (int j = i; j < history.size(); j++)
                    {
                        if (j - i + 1 > sizeof msg.text - 1)
                            break;
                        if(history[j] == '\n') // 单词的终点
                            r = j;  // 拷贝最终位置
                    }
                    strncpy(response.text, history.c_str() + i, r - i + 1);
                    cout << response.text;
                    i = r + 1; // 更新位置
                    // 将消息发送过去
                    if(send(sfd, response.Serialization().c_str(), Msg::getLen(), 0) < 0)
                    {   
                        ERR_LOG("send error");
                    }
                }
            }
            else
            {
                strcpy(response.text, "Historys is Null");
                if (send(sfd, response.Serialization().c_str(), Msg::getLen(), 0) < 0)
                {
                    ERR_LOG("send error");
                }
            }

            strcpy(response.text, "Send Over");
        }
        else
        {   // 非法类型
            strcpy(response.text, "Ivalid Commamd");
        }
        // 主机字节序转网络字节序
        if (send(sfd, response.Serialization().c_str(), Msg::getLen(), 0) < 0)
        {
            ERR_LOG("send error");
        }
    }

    close(sfd);
}

bool Server::stop()
{
    if(running_)
    {
        running_ = false;
    }
    return true;
}

string Server::getCurrentTime()
{
    // 获取当前的系统时间
    time_t now = time(NULL);
    // 将时间转换成结构体
    tm *local = localtime(&now);
    char time_str[20] = "";
    strftime(time_str, sizeof time_str, "%Y-%m-%d %H:%M:%S", local);
    return string(time_str);
}
